{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义类GeneSolve，它包含函数inter_cross、mutate、get_adjust、cycle_select分别为实现交叉、变异、计算适应度、以轮盘赌方式选择的代码\n",
    "\n",
    "函数get_decode对个体染色体进行解码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "import numpy as np\n",
    "\n",
    "def log(i,a,b):\n",
    "    print(\"epoch --> \",\n",
    "        str(i+1).rjust(5,\" \"),\" max:\",\n",
    "        str(round(a,4)).rjust(8,\" \"),\"mean:\",\n",
    "        str(round(b,4)).rjust(8,\" \"),\"alpha:\",\n",
    "        str(round(a/b,4)).rjust(8,\" \"))\n",
    "\n",
    "class GeneSolve:\n",
    "    def __init__(self, pop_size, epoch, cross_prob, mutate_prob, alpha, print_batch=10):\n",
    "        self.pop_size = pop_size\n",
    "        self.epoch = epoch\n",
    "        self.cross_prob = cross_prob\n",
    "        self.mutate_prob = mutate_prob\n",
    "        self.print_batch = print_batch\n",
    "        self.alpha = alpha\n",
    "        self.width = 11\n",
    "        self.best = None\n",
    "        \n",
    "        # 产生初始种群\n",
    "        self.genes = np.array([''.join([random.choice(['0','1']) for i in range(self.width)]) for j in range(self.pop_size)])\n",
    "    \n",
    "    def inter_cross(self):\n",
    "        \"\"\"对染色体进行交叉操作\"\"\"\n",
    "        ready_index = list(range(self.pop_size))\n",
    "        while len(ready_index) >= 2:\n",
    "            d1 = random.choice(ready_index)\n",
    "            ready_index.remove(d1)\n",
    "            d2 = random.choice(ready_index)\n",
    "            ready_index.remove(d2)\n",
    "            if np.random.uniform(0, 1) <= self.cross_prob:\n",
    "                loc = random.choice(range(1,self.width-1))\n",
    "                d1_a, d1_b = self.genes[d1][0:loc], self.genes[d1][loc:]\n",
    "                d2_a, d2_b = self.genes[d2][0:loc], self.genes[d2][loc:]\n",
    "                self.genes[d1] = d1_a + d2_b\n",
    "                self.genes[d2] = d2_a + d1_b\n",
    "                \n",
    "    def mutate(self):\n",
    "        \"\"\"基因突变\"\"\"\n",
    "        ready_index = list(range(self.pop_size))\n",
    "        for i in ready_index:\n",
    "            if np.random.uniform(0, 1) <= self.mutate_prob:\n",
    "                loc = random.choice(range(0,self.width))\n",
    "                t0 = list(self.genes[i])\n",
    "                t0[loc] = str(1 - int(self.genes[i][loc]))\n",
    "                self.genes[i] = ''.join(t0)\n",
    "                \n",
    "    def get_adjust(self):\n",
    "        \"\"\"计算适应度\"\"\"\n",
    "        x = self.get_decode()\n",
    "        return x*np.sin(x)+12\n",
    "    \n",
    "    def get_decode(self):\n",
    "        return np.array([int(x,2)*12.55/(2**11-1) for x in self.genes])\n",
    "    \n",
    "    def cycle_select(self):\n",
    "        \"\"\"通过轮盘赌来进行选择\"\"\"\n",
    "        adjusts = self.get_adjust()\n",
    "        if self.best is None or np.max(adjusts) > self.best[1]:\n",
    "            self.best = self.genes[np.argmax(adjusts)], np.max(adjusts)\n",
    "        p = adjusts/np.sum(adjusts)\n",
    "        cu_p = []\n",
    "        for i in range(self.pop_size):\n",
    "            cu_p.append(np.sum(p[0:i]))\n",
    "        cu_p = np.array(cu_p)\n",
    "        r0 = np.random.uniform(0,1,self.pop_size)\n",
    "        sel = [max(list(np.where(r > cu_p)[0])+[0]) for r in r0]\n",
    "        # 保留最优的个体\n",
    "        if np.max(adjusts[sel]) < self.best[1]:\n",
    "            self.genes[sel[np.argmin(adjusts[sel])]] = self.best[0]\n",
    "        self.genes = self.genes[sel]\n",
    "        \n",
    "    def evolve(self):\n",
    "        for i in range(self.epoch):\n",
    "            self.cycle_select()\n",
    "            self.inter_cross()\n",
    "            self.mutate()\n",
    "            a,b=np.max(gs.get_adjust()),np.mean(gs.get_adjust())\n",
    "            if i%self.print_batch == self.print_batch - 1 or i==0:\n",
    "                log(i,a,b)\n",
    "            if a/b < self.alpha:\n",
    "                log(i,a,b)\n",
    "                print(\"进化终止，算法已收敛！共进化 \",i+1,\" 代！\")\n",
    "                break"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "创建一个GeneSolve类的实例，给定初始种群规模为100，即100个个体，最大迭代次数500次，0.85的交叉概率以及0.1的变异概率，当种群中最大适应度与平均适应度的比值低于给定的1.02时，终止迭代"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch -->      1  max:  19.9167 mean:  14.5231 alpha:   1.3714\n",
      "epoch -->    100  max:  19.9167 mean:  19.2476 alpha:   1.0348\n",
      "epoch -->    101  max:  19.9167 mean:  19.6552 alpha:   1.0133\n",
      "进化终止，算法已收敛！共进化  101  代！\n"
     ]
    }
   ],
   "source": [
    "gs = GeneSolve(100, 500, 0.85, 0.1, 1.02,100)\n",
    "gs.evolve()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('10100010101', 19.916705125479506)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gs.best"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
